﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using UIDesigner.DesignContainers.Bases;
using UIDesigner.SurfaceProperties;
using System.Windows.Forms.Design;
using AFSharedLibrary;
using DDW;
using AFSharedLibrary.Wizards;
using System.Diagnostics;
using SharedClasses;
using System.Threading;
using UIDesigner.SurfaceProperties.Operations;
using UIDesigner.SurfaceProperties.Information;

namespace UIDesigner.Designers.Controls
{
    public partial class ctrlCreateNewWizard : UserControl, IWizardFrameContainer
    {
        private const int WM_UNHOOK = (int)WindowsAPI.WindowsMessage.WM_USER + 53248;
        private AFDesignerHost m_objHost;
        private IBaseObjectControl m_objControl;
        private CreateOptions m_eCreateOptions;
        private IWindowsFormsEditorService m_objEditorService;
        private DialogResult m_eResult = DialogResult.Cancel;
        private ctrlWizFrameBase m_ctrlCurrentFrame;
        private Label lblCaption;
        private Button cmdCancel;
        private Button cmdNext;
        private Button cmdBack;
        private Button cmdFinish;
        private Rectangle m_rcList;
        private static int m_fnOldParentWndProc;
        private static bool m_bUnhookPosted;
        private static ctrlCreateNewWizard m_ctrlThis;
        private static WindowsAPI.WindowProc m_fnNewParentWndProc;
        private static Image m_objScreenImage;
        private Dictionary<string, ctrlWizFrameBase> m_rgFrameCache = new Dictionary<string, ctrlWizFrameBase>();

        #region " Windows Form Designer generated code "

        //Form overrides dispose to clean up the component list.
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!(components == null))
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        //Required by the Windows Form Designer
        private System.ComponentModel.IContainer components;

        //NOTE: The following procedure is required by the Windows Form Designer
        //It can be modified using the Windows Form Designer.  
        //Do not modify it using the code editor.
        internal System.Windows.Forms.PictureBox PictureBox;
        internal System.Windows.Forms.Panel ctrlFramePlaceHolder;
        [System.Diagnostics.DebuggerStepThrough()]
        private void InitializeComponent()
        {
            this.PictureBox = new System.Windows.Forms.PictureBox();
            this.ctrlFramePlaceHolder = new System.Windows.Forms.Panel();
            this.lblCaption = new System.Windows.Forms.Label();
            this.cmdCancel = new System.Windows.Forms.Button();
            this.cmdNext = new System.Windows.Forms.Button();
            this.cmdBack = new System.Windows.Forms.Button();
            this.cmdFinish = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.PictureBox)).BeginInit();
            this.SuspendLayout();
            // 
            // PictureBox
            // 
            this.PictureBox.BackColor = System.Drawing.SystemColors.ControlText;
            this.PictureBox.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.PictureBox.Location = new System.Drawing.Point(15, 39);
            this.PictureBox.Name = "PictureBox";
            this.PictureBox.Size = new System.Drawing.Size(248, 336);
            this.PictureBox.TabIndex = 0;
            this.PictureBox.TabStop = false;
            // 
            // ctrlFramePlaceHolder
            // 
            this.ctrlFramePlaceHolder.Location = new System.Drawing.Point(271, 39);
            this.ctrlFramePlaceHolder.Name = "ctrlFramePlaceHolder";
            this.ctrlFramePlaceHolder.Size = new System.Drawing.Size(400, 336);
            this.ctrlFramePlaceHolder.TabIndex = 4;
            // 
            // lblCaption
            // 
            this.lblCaption.BackColor = System.Drawing.Color.Navy;
            this.lblCaption.ForeColor = System.Drawing.Color.White;
            this.lblCaption.Location = new System.Drawing.Point(12, 8);
            this.lblCaption.Name = "lblCaption";
            this.lblCaption.Size = new System.Drawing.Size(659, 23);
            this.lblCaption.TabIndex = 5;
            this.lblCaption.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // cmdCancel
            // 
            this.cmdCancel.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.cmdCancel.Location = new System.Drawing.Point(604, 391);
            this.cmdCancel.Name = "cmdCancel";
            this.cmdCancel.Size = new System.Drawing.Size(67, 23);
            this.cmdCancel.TabIndex = 3;
            this.cmdCancel.Text = "Cancel";
            this.cmdCancel.Click += new System.EventHandler(this.cmdCancel_Click);
            // 
            // cmdNext
            // 
            this.cmdNext.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.cmdNext.Location = new System.Drawing.Point(443, 391);
            this.cmdNext.Name = "cmdNext";
            this.cmdNext.Size = new System.Drawing.Size(67, 23);
            this.cmdNext.TabIndex = 2;
            this.cmdNext.Text = "&Next >";
            this.cmdNext.Click += new System.EventHandler(this.cmdNext_Click);
            // 
            // cmdBack
            // 
            this.cmdBack.Enabled = false;
            this.cmdBack.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.cmdBack.Location = new System.Drawing.Point(370, 391);
            this.cmdBack.Name = "cmdBack";
            this.cmdBack.Size = new System.Drawing.Size(67, 23);
            this.cmdBack.TabIndex = 1;
            this.cmdBack.Text = "< &Back";
            this.cmdBack.Click += new System.EventHandler(this.cmdBack_Click);
            // 
            // cmdFinish
            // 
            this.cmdFinish.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.cmdFinish.Location = new System.Drawing.Point(516, 391);
            this.cmdFinish.Name = "cmdFinish";
            this.cmdFinish.Size = new System.Drawing.Size(67, 23);
            this.cmdFinish.TabIndex = 2;
            this.cmdFinish.Text = "Finish";
            this.cmdFinish.Click += new System.EventHandler(this.cmdFinish_Click);
            // 
            // ctrlCreateNewWizard
            // 
            this.Controls.Add(this.lblCaption);
            this.Controls.Add(this.ctrlFramePlaceHolder);
            this.Controls.Add(this.cmdCancel);
            this.Controls.Add(this.cmdFinish);
            this.Controls.Add(this.cmdNext);
            this.Controls.Add(this.cmdBack);
            this.Controls.Add(this.PictureBox);
            this.Name = "ctrlCreateNewWizard";
            this.Size = new System.Drawing.Size(686, 424);
            ((System.ComponentModel.ISupportInitialize)(this.PictureBox)).EndInit();
            this.ResumeLayout(false);

        }
        #endregion

        public ctrlCreateNewWizard(AFDesignerHost objHost, IBaseObjectControl objControl, Rectangle rcList, IWindowsFormsEditorService objEditorService, CreateOptions eCreateOptions)
        {
            m_objHost = objHost;
            m_objControl = objControl;
            m_eCreateOptions = eCreateOptions;
            m_objEditorService = objEditorService;

            m_fnOldParentWndProc = 0;
            m_bUnhookPosted = false;
            m_fnNewParentWndProc = null;
            m_objScreenImage = null;

            this.Size = new System.Drawing.Size(682, 426);

            m_ctrlThis = this;
            m_rcList = rcList;
        }

        private static int ParentWindowProc(int hWnd, int uMsg, int wParam, int lParam)
        {
            try
            {
                if (uMsg == (int)WindowsAPI.WindowsMessage.WM_NCPAINT || uMsg == (int)WindowsAPI.WindowsMessage.WM_PAINT || uMsg == (int)WindowsAPI.WindowsMessage.WM_ERASEBKGND)
                {
                    if (!m_bUnhookPosted)
                    {
                        m_bUnhookPosted = true;
                        WindowsAPI.SendMessage(m_ctrlThis.Handle.ToInt32(), WM_UNHOOK, 0, 0);
                    }
                }

                return WindowsAPI.CallWindowProc(m_fnOldParentWndProc, hWnd, uMsg, wParam, lParam);
            }
            catch (Exception e)
            {
                Debugger.Break();
            }

            return 0;
        }

        protected override void WndProc(ref Message m)
        {
            try
            {
                if (m.Msg == (int)WindowsAPI.WindowsMessage.WM_CREATE)
                {
                    int hwnd = this.Parent.Handle.ToInt32();

                    m_fnNewParentWndProc = ParentWindowProc;

                    if (m_fnOldParentWndProc == 0)
                    {
                        m_fnOldParentWndProc = WindowsAPI.SetWindowLong(hwnd, WindowsAPI.WindowLongIndex.GWL_WNDPROC, m_fnNewParentWndProc);
                        SubclassTracker.AddProc(hwnd, m_fnNewParentWndProc, m_fnOldParentWndProc);
                    }

                    WindowsAPI.AssertAPI(m_fnOldParentWndProc != 0);
                }
                else if (m.Msg == WM_UNHOOK)
                {
                    int fnOldParentWndProc;
                    int hwnd = this.Parent.Handle.ToInt32();

                    WindowsAPI.SetWindowLong(hwnd, WindowsAPI.WindowLongIndex.GWL_WNDPROC, m_fnOldParentWndProc);
                    SubclassTracker.RemoveProc(m_fnNewParentWndProc);

                    fnOldParentWndProc = m_fnOldParentWndProc;
                    m_fnOldParentWndProc = 0;

                    WindowsAPI.RECT rc = new WindowsAPI.RECT();

                    WindowsAPI.GetWindowRect(hwnd, ref rc);

                    m_objScreenImage = ScreenCapture.CaptureScreen(rc.Left, rc.Top, RectMath.Width(rc), RectMath.Height(rc));
                    Animate(RectMath.ConvertToFCL(rc));
                }

                base.WndProc(ref m);
            }
            catch (Exception e)
            {
                Debugger.Break();
                base.WndProc(ref m);
            }
        }

        private void Animate(Rectangle rcTarget)
        {
            int nLeftDiff = rcTarget.Left - m_rcList.Left;
            int nTopDiff = rcTarget.Top - m_rcList.Top;
            int nRightDiff = rcTarget.Right - m_rcList.Right;
            int nBottomDiff = rcTarget.Bottom - m_rcList.Bottom;
            int hwnd = this.Handle.ToInt32();
            int hdc = WindowsAPI.GetDC(hwnd);
            WindowsAPI.RECT rc = RectMath.ConvertToAPI(m_rcList);
            WindowsAPI.RECT rcLast = new WindowsAPI.RECT();
            int hBrush = WindowsAPI.GetStockObject(WindowsAPI.StockObjects.NULL_BRUSH);
            int hOldBrush;
            int hPen = WindowsAPI.GetStockObject(WindowsAPI.StockObjects.NULL_PEN);

            hOldBrush = WindowsAPI.SelectObject(hdc, hBrush);
            ControlUtils.ScreenToClient(hwnd, ref rc);

            for (int x = 0; x < 20; x++)
            {
                rc.Left += (nLeftDiff / 20);
                rc.Top += (nTopDiff / 20);
                rc.Right += (nRightDiff / 20);
                rc.Bottom += (nBottomDiff / 20);

                DrawingUtils.DrawBitmap(hdc, rc.Left - 1, rc.Top - 1, RectMath.Width(rc), RectMath.Height(rc), rc.Left, rc.Top, (Bitmap)m_objScreenImage);

                WindowsAPI.Rectangle(hdc, rc.Left, rc.Top + 1, rc.Right, rc.Bottom);

                rcLast = rc;
            }

            WindowsAPI.SelectObject(hdc, hOldBrush);

            WindowsAPI.ReleaseDC(hwnd, hdc);

            InitializeComponent();
            LoadFirstFrame();
        }

        public ctrlWizFrameBase CurrentFrame
        {
            get
            {
                return m_ctrlCurrentFrame;
            }

            set
            {
                m_ctrlCurrentFrame = value;
            }
        }

        private void cmdCancel_Click(System.Object sender, System.EventArgs e)
        {
            m_eResult = DialogResult.Cancel;
            m_objEditorService.CloseDropDown();
        }

        private void LoadFirstFrame()
        {
            Construct objConstruct = m_objControl.BusinessObject;

            if (objConstruct.ConstructorMap.Count > 1)
            {
                this.CurrentFrame = new ctrlWizPanelConstructors(null, this);
            }
            else
            {
                this.CurrentFrame = new ctrlWizPanelButtonOptions(null, this);
            }

            ShowFrame(m_ctrlCurrentFrame);
        }

        public ctrlWizFrameBase GetFromCache(string szName)
        {
            ctrlWizFrameBase ctrlBase;

            ctrlBase = m_rgFrameCache[szName];

            if (ctrlBase != null)
            {
                return ctrlBase;
            }
            else
            {
                return null;
            }
        }

        private bool ShowFromCache(int nIndex)
        {
            foreach (ctrlWizFrameBase ctrlBase in m_rgFrameCache.Values)
            {
                if (ctrlBase.Index == nIndex)
                {
                    m_ctrlCurrentFrame.Visible = false;

                    ShowFrame(ctrlBase);
                    return true;
                }
            }

            return false;
        }

        private void ShowFrame(ctrlWizFrameBase ctrlFrame)
        {
            ctrlFrame.Location = new System.Drawing.Point(0, 0);
            ctrlFrame.Size = new System.Drawing.Size(ctrlFramePlaceHolder.Width, ctrlFramePlaceHolder.Height);

            ctrlFrame.Dock = DockStyle.Fill;

            ctrlFramePlaceHolder.Controls.Add(ctrlFrame);

            ctrlFrame.Visible = true;

            lblCaption.Text = "Create New Object Wizard - " + ctrlFrame.Caption;

            ctrlFrame.ResumeLayout(false);
            ctrlFramePlaceHolder.ResumeLayout(false);

            if (!m_rgFrameCache.ContainsKey(ctrlFrame.Name))
            {
                m_rgFrameCache.Add(ctrlFrame.Name, ctrlFrame);
            }

            m_ctrlCurrentFrame = ctrlFrame;
        }

        private void Finish()
        {
            int x = 0;
            int y = 0;
            Construct objConstruct = this.BusinessObject;
            ctrlWizPanelConstructors ctrlWizPanelConstructors = null;
            ctrlWizPanelButtonOptions ctrlWizPanelButtonOptions = null;
            ctrlWizPanelPanelOptions ctrlWizPanelPanelOptions = null;
            SurfacePropertiesBase objSurfaceProperties = m_objHost.SurfacePropertiesSet[m_objControl];
            CreateProperties objCreateProperties;
            ConstructorOptions eConstructorOptions = ConstructorOptions.Uninitialized;
            CreateButtonOptions eCreateButtonOptions = CreateButtonOptions.Uninitialized;

            if (m_rgFrameCache.ContainsKey("ctrlWizPanelConstructors"))
            {
                ctrlWizPanelConstructors = (ctrlWizPanelConstructors)m_rgFrameCache["ctrlWizPanelConstructors"];
            }

            if (m_rgFrameCache.ContainsKey("ctrlWizPanelButtonOptions"))
            {
                ctrlWizPanelButtonOptions = (ctrlWizPanelButtonOptions)m_rgFrameCache["ctrlWizPanelButtonOptions"];
            }

            if (m_rgFrameCache.ContainsKey("ctrlWizPanelPanelOptions"))
            {
                ctrlWizPanelPanelOptions = (ctrlWizPanelPanelOptions)m_rgFrameCache["ctrlWizPanelPanelOptions"];
            }

            objSurfaceProperties.CreateProperties.CreateOptions = m_eCreateOptions;

            if (ctrlWizPanelConstructors == null)
            {
                eConstructorOptions = ConstructorOptions.OptionsPanel;
            }
            else
            {
                if (ctrlWizPanelConstructors.optCreateOptionsPanel.Checked)
                {
                    eConstructorOptions = ConstructorOptions.OptionsPanel;
                }
                else if (ctrlWizPanelConstructors.optSelectDefaultConstructor.Checked)
                {
                    eConstructorOptions = ConstructorOptions.DefaultConstructor;
                }
                else
                {
                    Debugger.Break();
                }
            }

            if (ctrlWizPanelButtonOptions == null)
            {
                eCreateButtonOptions = CreateButtonOptions.Link;
            }
            else
            {
                if (ctrlWizPanelButtonOptions.optButton.Checked)
                {
                    eCreateButtonOptions = CreateButtonOptions.Button;
                }
                else if (ctrlWizPanelButtonOptions.optLink.Checked)
                {
                    eCreateButtonOptions = CreateButtonOptions.Link;
                }
                else
                {
                    Debugger.Break();
                }
            }

            objCreateProperties = new CreateProperties(eConstructorOptions, eCreateButtonOptions);

            objCreateProperties.ObjectName = m_objControl.BusinessObject.Name;
            objCreateProperties.CreateOptions = m_eCreateOptions;

            foreach (ConstructorMapItem objConstructorMapItem in objConstruct.ConstructorMap)
            {
                ctrlWizPanelOptionLabels ctrlWizPanelOptionLabels = null;
                SurfaceConstructorInfo objSurfaceConstructorInfo = new SurfaceConstructorInfo(objConstructorMapItem);

                if (m_rgFrameCache.ContainsKey("ctrlWizPanelOptionLabels" + x.ToString()))
                {
                    ctrlWizPanelOptionLabels = (ctrlWizPanelOptionLabels)m_rgFrameCache["ctrlWizPanelOptionLabels" + x.ToString()];
                }

                y = 0;

                foreach (ParmItem objParmItem in objConstructorMapItem.ParmItems.Values)
                {
                    SurfaceParmInfo objSurfaceParmInfo = null;

                    if (ctrlWizPanelOptionLabels == null)
                    {
                        objSurfaceParmInfo = new SurfaceParmInfo(objParmItem.Name, objParmItem);
                    }
                    else
                    {
                        TextBox txtLabel = ctrlWizPanelOptionLabels.LabelTextBoxes[y];

                        objSurfaceParmInfo = new SurfaceParmInfo(txtLabel.Text, objParmItem);
                    }

                    objSurfaceConstructorInfo.ParmInfos.Add(objSurfaceParmInfo);

                    y++;
                }

                objCreateProperties.ConstructorInfos.Add(objSurfaceConstructorInfo);

                x++;
            }

            objSurfaceProperties.CreateProperties = objCreateProperties;

            m_objEditorService.CloseDropDown();
            m_eResult = DialogResult.OK;
        }

        private void cmdNext_Click(System.Object sender, System.EventArgs e)
        {
            ctrlWizFrameBase ctrlNext;

            if (cmdNext.Visible == false)
            {
                Finish();
            }
            else
            {
                cmdBack.Enabled = true;

                if (!ShowFromCache(m_ctrlCurrentFrame.Index + 1))
                {
                    ctrlNext = m_ctrlCurrentFrame.GetNextFrame(m_ctrlCurrentFrame);

                    m_ctrlCurrentFrame.Visible = false;

                    if (ctrlNext != null)
                    {
                        ctrlNext.Index = m_ctrlCurrentFrame.Index + 1;
                        ShowFrame(ctrlNext);
                    }
                    else
                    {
                        lblCaption.Text = "Create New Object Wizard - Finished";
                        cmdNext.Visible = false;
                    }
                }
            }
        }

        private void cmdBack_Click(System.Object sender, System.EventArgs e)
        {
            ctrlWizFrameBase ctrlPrevious;
            ctrlWizFrameBase ctrlPrevious2;

            if (cmdNext.Visible == false)
            {
                cmdNext.Visible = true;
                ShowFrame(m_ctrlCurrentFrame);
            }
            else
            {
                ctrlPrevious = m_ctrlCurrentFrame.PreviousFrame;
                m_ctrlCurrentFrame.Visible = false;

                if (ctrlPrevious != null)
                {
                    ctrlPrevious2 = ctrlPrevious.PreviousFrame;

                    if (ctrlPrevious2 == null)
                    {
                        cmdBack.Enabled = false;
                    }

                    ShowFrame(ctrlPrevious);
                }
            }
        }

        public DialogResult DialogResult
        {
            get
            {
                return m_eResult;
            }
        }

        public Construct BusinessObject
        {
            get
            {
                return m_objControl.BusinessObject;
            }
        }

        private void ctrlCreateNewOptions_Load(object sender, EventArgs e)
        {
            ClassNode objNode = this.BusinessObject.Node as ClassNode;

            if (objNode != null)
            {

            }
        }

        private void cmdFinish_Click(object sender, EventArgs e)
        {
            Finish();
        }
    }
}
